'''
    This file is part of Ognom Keeper.

    Ognom Keeper is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Ognom Keeper is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Ognom Keeper.  If not, see <http://www.gnu.org/licenses/>.


    Copyright(C) 2009 Viktor Vestberg
'''

try: 
    import tkFileDialog as tk
    import tkSimpleDialog as tks
    from Tkinter import *
    from factory import *
    from state import *

except ImportError, err:
    print str("couldn't load module. %s" % (err))

class LvEditState(State):
   def init(self):
        self.input.makeKeypart(pygame.K_ESCAPE, [self.parent.runFallBackState])
   def __init__(self):
        self.manager       = Manager()
        self.input         = Input()
        self.renderer      = Renderer()
        self.text          = Text()
        self.bgHandler     = BgHandler()
        self.physics       = Physics()
        self.entityHandler = EntityHandler()
        self.camera        = Camera()
        self.menu          = Menu(self.text, self.input)
        self.playerFactory = PlayerFactory(self.entityHandler, self.renderer, self.physics, self.input)
        self.Wallfactory = WallFactory(self.entityHandler, self.renderer, self.physics)
        self.levelEditor = LevelEditor(self.Wallfactory, self.playerFactory)
        
        self.levelLoader = LevelLoader(self.Wallfactory, self.playerFactory)
        
        
        self.levelLoader.addUpdaters([self.bgHandler, self.camera, self.renderer, self.levelEditor, self.playerFactory])
        self.currentBg = 'empty.jpg'
        self.currentGravity = (0.0,200.0)
        level = self.levelLoader.loadLevel('empty.map', self.currentBg)
        
        self.manager.addHandler([self.physics, self.input, self.entityHandler, self.bgHandler,
                                 self.renderer, self.camera, self.text, self.menu, self.levelEditor])
        
        self.tk = Tk()
        self.input.makeMouseKeypart(1, [self.levelEditor.addMousePos])
        self.input.makeMouseKeypart(3, [self.levelEditor.addObject])
        
        self.physics.pause()
        
        save = self.menu.makePart(self.saveLevel, "Save level", (70,630), 10, None, [0,0,255],[255,255,255])
        load = self.menu.makePart(self.loadLevel, "Load Level", (90,630), 10, None, [0,0,255],[255,255,255])
        loadbg = self.menu.makePart(self.loadBg, "Load Bg", (110,630), 10, None, [0,0,255],[255,255,255])
        clear = self.menu.makePart(self.levelEditor.cleanLevel, "Clean Level", (130,630), 10, None, [0,0,255],[255,255,255])
        
        walls = self.menu.makePart(self.levelEditor.changeAdder, "Add walls", (170,630), 10, 'wall', [0,0,255],[255,255,255])
        polys = self.menu.makePart(self.levelEditor.changeAdder, "Add Player", (190,630), 10, 'player', [0,0,255],[255,255,255])
        badwall = self.menu.makePart(self.levelEditor.changeAdder, "Add Badwall", (210,630), 10, 'badwall', [0,0,255],[255,255,255])
        finish = self.menu.makePart(self.levelEditor.changeAdder, "Add Finish", (230,630), 10, 'finish', [0,0,255],[255,255,255])
        bounce = self.menu.makePart(self.levelEditor.changeAdder, "Add Bouncewall", (250,630), 10, 'bouncewall', [0,0,255],[255,255,255])
        gravity = self.menu.makePart(self.setGravity, "Set gravity", (290,630), 10, None, [0,0,255],[255,255,255])
        rootfolder = [save, load, clear, walls, polys, finish, badwall, loadbg, bounce, gravity]
        self.menu.setCurrentFolder(rootfolder)
        
   def loadBg(self):
       self.currentBg = tk.askopenfilename(initialdir='maps')
       self.levelLoader.updateBg(self.currentBg)
   def loadLevel(self):
       filename = tk.askopenfilename(initialdir='maps')
       self.levelLoader.loadLevel(str(filename))
   def saveLevel(self):
       filename = tk.asksaveasfilename(initialdir='maps', defaultextension='.map').rsplit('/')[-1]
       self.levelEditor.saveLevel(str(filename), self.currentBg.rsplit('/')[-1], self.currentGravity)
   def setGravity(self):
       vGravity = tks.askfloat('Set Gravity', 'Vertical gravity:', initialvalue=200.0, parent=self.tk)
       hGravity = tks.askfloat('Set Gravity', 'Horizontal gravity:', initialvalue=0.0, parent=self.tk)
       self.currentGravity = (hGravity, vGravity)
       
       

class LevelEditor(Handler):
    """This class can save levels and construct them. It can add different types of objects to a map"""
    def __init__(self, wallFactory, playerFactory):
        self.allPoints = []
        self.points = []
        self.finishPoints = []
        self.badWallPoints = []
        self.bounceWallPoints = []
        self.wallFactory = wallFactory
        self.playerFactory = playerFactory
        self.wallColor = [0,0,0]
        self.bgRect = None
        self.visibleWalls = True
        self.currentAdder = 'wall'
        self.surface = pygame.display.get_surface()
    def update(self):
        if self.currentAdder is not 'player':
            self.updateWalls()
    def updateWalls(self):
        if len(self.points) > 0:
            endpoint = pygame.mouse.get_pos()
            startpoint = (self.points[-1][0]-self.bgRect.left, self.points[-1][1]-self.bgRect.top)
            pygame.draw.aaline(self.surface, [255,255,255], startpoint, endpoint)
        if len(self.points) > 1:
            points = [(point[0]-self.bgRect.left, point[1]-self.bgRect.top) for point in self.points]
            pygame.draw.aalines(self.surface, [255,255,255], False, points, 1)
            
    def addMousePos(self):
        point = pygame.mouse.get_pos()[0]+self.bgRect.left, pygame.mouse.get_pos()[1]+self.bgRect.top
        self.points.append(point)
    def changeAdder(self, string='wall'):
        self.currentAdder = string
        self.points = []
    def addObject(self):
        if len(self.points) <= 1: self.points = []
        elif self.currentAdder is 'wall':
            self.addWall()
        elif self.currentAdder is 'finish':
            self.addFinish()
        elif self.currentAdder is 'badwall':
            self.addBadWall()
        elif self.currentAdder is 'bouncewall':
            self.addBounceWall()
        if self.currentAdder is 'player':
            self.addPlayer()

    def addPlayer(self):
        self.playerFactory.makePlayer()
    def addWall(self):
        self.wallFactory.makeWall(self.points, self.wallColor, self.visibleWalls)
        self.allPoints.append(self.points)
        self.points = []
    def addFinish(self):
        self.wallFactory.makeWall(self.points, [255,0,254], self.visibleWalls, 3)
        self.finishPoints.append(self.points)
        self.points = []
    def addBadWall(self):
        self.wallFactory.makeWall(self.points, [255,0,0], self.visibleWalls, 4)
        self.badWallPoints.append(self.points)
        self.points = []
    def addBounceWall(self):
        self.wallFactory.makeWall(self.points, [0,0,160], self.visibleWalls, 2, 4)
        self.bounceWallPoints.append(self.points)
        self.points = []
    def setBgRect(self, rect):
        self.bgRect = rect
    def setBgSurface(self, surf):
        self.bgSurf = surf
    def setBgPicture(self, pic):
        self.bgPic = pic
    def saveLevel(self, filename='untitled.map', picname='level1.jpg', gravity=100):
        file = open(os.path.join('maps', filename),'wb')
        level = Level()
        for points in self.allPoints:
            level.wallPoints.append(points)
        try: 
            player = self.playerFactory.players[-1]
            level.playerStartPos = (player.X, player.Y)
        except IndexError: level.playerStartPos = None
        level.bgPicture = picname
        level.gravity = gravity
        level.finishPoints = self.finishPoints
        level.badWallPoints = self.badWallPoints
        level.bounceWallPoints = self.bounceWallPoints
        pickle.dump( level, file, 0 )
        print "File", filename, "has been saved!"
        file.close()
    def cleanLevel(self):
        self.playerFactory.clean()
        self.wallFactory.clean()
        self.allPoints = []
        self.finishPoints = []
